package com.finch.nio;


import org.junit.Test;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

/**
 * @author Levi Wang
 * @create 2021-07-11 13:31
 *
 * 一、缓冲区（Buffer）:在Java NIO中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据
 *
 * 根据数据类型不同（boolean除外），提供了相应类型的缓冲区
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 *
 * 上述缓冲区的管理方式几乎一致，通过allocate（）获取缓冲区
 *
 * 二、缓冲区存取数据的和核心方法：
 * put()  : 存入数据到缓冲区
 * get() : 获取缓冲区中的数据
 *
 *
 * 三、缓冲区中的四个核心属性
 * capacity  容量，缓冲区最大容量，一旦声明不能改变，因为其底层是数组
 * limit   界限，表示缓冲区中可以操作数据的大小，即limit后面的数据是不能读写的
 * position  位置，表示缓冲区中正在操作数据的位置
 * mark   标记，表示记录当前position的位置。可以通过reset()恢复到Mark的位置
 *
 *  0 <= position <= limit <= capacity
 *
 *
 *
 *
 *
 *  五、直接缓冲区与非直接缓冲区
 *
 *  非直接缓冲区：通过allocate（）方法分配缓冲区，将缓冲区建立在JVM的内存中
 *
 *  直接缓冲区通过allocateDirect()方法分配直接缓冲区，将缓冲区建立在物理内存中（物理内存映射文件）。
 *  可以提高效率，但是不安全，而且内存消耗大，不易控制；
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

public class TestBuffer {

    @Test
    public void test1(){

        String str = "abcde";

        //1、分配一个指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        System.out.println("----------allocate()-------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        //2、利用put()方法 存入数据到缓冲区;写数据模式
        buf.put(str.getBytes());

        System.out.println("----------put()-------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        //3、利用flip()切换到读数据模式，缓冲区的position和limit属性都会随之变化
        buf.flip();
        System.out.println("----------flip()-------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        //4、利用get() 读取缓冲区中的数据
        System.out.println("----------get()-------------");
        byte[] dst = new byte[buf.limit()];
        buf.get(dst);
        System.out.println(new String(dst, 0, dst.length));

        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        //5、rewind() : 可重复读数据
        buf.rewind();
        System.out.println("----------rewind()-------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        //6、clear()  清空缓冲区,回到最初状态；但是里面的数据还在，只不过这些数据处于“被遗忘状态”
        buf.clear();
        System.out.println("----------clear()-------------");
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());

        System.out.println((char) buf.get());



    }


    @Test
    public void test2(){

        String str = "abcde";

        ByteBuffer buf = ByteBuffer.allocate(1024);

        buf.put(str.getBytes());

        buf.flip();

        byte[] dst = new byte[buf.limit()];
        buf.get(dst,0,2);
        System.out.println(new String(dst, 0, 2));

        System.out.println(buf.position());

        //mark() 标记
        buf.mark();

        buf.get(dst, 2, 2);
        System.out.println(new String(dst,2,2));
        System.out.println(buf.position());

        //reset()  把position恢复到mark的位置
        buf.reset();
        System.out.println(buf.position());

        //判断缓冲区中是否还有剩余数据
        if (buf.hasRemaining()) {

            //获取缓冲区中可以操作的数量
            System.out.println(buf.remaining());
        }



    }



    @Test
    public void test3(){
        //分配直接缓冲区
        ByteBuffer buf = ByteBuffer.allocateDirect(1024);

        //判断是否是直接缓冲区
        System.out.println(buf.isDirect());

    }








}






















